package com.ryenlii.datatrans.core.config;

import com.ryenlii.datatrans.core.annotations.ExchangeClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;

import java.util.Map;
import java.util.Set;

public class ExchangeClientsRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        ClassPathExchangeScanner scanner = new ClassPathExchangeScanner(registry);
        // 扫描带@ExchangeClient的类
        scanner.addIncludeFilter(new AnnotationTypeFilter(ExchangeClient.class));
        scanner.scan(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
    }

    @Slf4j
    private static class ClassPathExchangeScanner extends ClassPathBeanDefinitionScanner {
        public ClassPathExchangeScanner(BeanDefinitionRegistry registry) {
            super(registry, false);
        }

        public Set<BeanDefinitionHolder> doScan(String... basePackages) {
            Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
            if (!beanDefinitions.isEmpty()) {
                for (BeanDefinitionHolder holder : beanDefinitions) {
                    AbstractBeanDefinition definition = (AbstractBeanDefinition) holder.getBeanDefinition();
                    String beanClassName = definition.getBeanClassName();
                    // 把类名注入
                    definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
                    // 指定FactoryBean生成
                    definition.setBeanClass(HttpExchangeFactoryBean.class);
                    if (definition instanceof AnnotatedBeanDefinition) {
                        // verify annotated class is an interface
                        AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) definition;
                        AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
                        Map<String, Object> attributes = annotationMetadata
                                .getAnnotationAttributes(ExchangeClient.class.getCanonicalName());
                        String baseUrl = (String) attributes.get("value");
                        // 把域名注入 这里的spel不用解释好  spring会自动解释
                        definition.getPropertyValues().add("baseUrl", baseUrl);
                    }
                }
            }
            return beanDefinitions;
        }

        protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
            return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
        }
    }

}